﻿#pragma once

#include "OCMain/cnpy.h"

using namespace OCPP;
using namespace cnpy;

std::tuple<size_t, size_t, size_t, size_t> readDim(String fileName)
{
	FILE* fp = fopen(fileName.c_str(), "rb");
	size_t word_size;
	std::vector<size_t> dims;
	bool fortran_order;
	parse_npy_header(fp, word_size, dims, fortran_order);
	fclose(fp);
	dims.resize(3);
	return std::make_tuple(word_size, dims[0], dims[1], dims[2]);
}

int32 getInt(size_t i, NpyArray& dataArray)
{
	if (dataArray.word_size == 8)
	{
		return (int32)dataArray.data<int64>()[i];
	}
	else if (dataArray.word_size == 4)
	{
		return dataArray.data<int32>()[i];
	}

	return 0;
}

float getFloat(size_t i, NpyArray& dataArray)
{
	if (dataArray.word_size == 8)
	{
		return (float)dataArray.data<double>()[i];
	}
	else if (dataArray.word_size == 4)
	{
		return dataArray.data<float>()[i];
	}

	return 0.0f;
}

#define PATH "e:/volume/data/npy"

std::tuple<float, float, float, float> readExtent()
{
	String fileName1 = joinPath(PATH,"longitude.npy");
	String fileName2 = joinPath(PATH,"latitude.npy");
	auto [word_size, dimZ1, dimY1, dimX1] = readDim(fileName1);
	auto [word_size2, dimZ2, dimY2, dimX2] = readDim(fileName2);
	NpyArray dataArray1 = npy_load(fileName1.c_str());
	NpyArray dataArray2 = npy_load(fileName2.c_str());
	float west = 0.0f, south = 0.0f, east = 0.0f, north = 0.0f;

	west = east = getFloat(0, dataArray1);
	south = north = getFloat(0, dataArray2);

	for (auto i = 1; i < dimZ1; i++)
	{
		float value = getFloat(i, dataArray1);
		if (value < west) west = value;
		if (value > east) east = value;
	}

	for (auto i = 1; i < dimZ2; i++)
	{
		float value = getFloat(i, dataArray2);
		if (value < south) south = value;
		if (value > north) north = value;
	}

	south = getFloat(0, dataArray2);
	north = getFloat(dimZ2 - 1, dataArray2);
	return std::make_tuple(west, south, east, north);
}

void getHeight()
{
	String fileName1 = joinPath(PATH, "height.npy");
	NpyArray dataArray1 = npy_load(fileName1.c_str());
	auto [word_size, dimZ, dimY, dimX] = readDim(fileName1);
	float height0 = getInt(0, dataArray1);
	float height1 = height0;
	for (auto i = 1; i < dimZ; i++)
	{
		float value = getInt(i, dataArray1);
		if (value < height0) height0 = value;
		if (value > height1) height1 = value;
	}
	OCPP_LOG_INFO << "HeightRange:[" << height0 << "," << height1 << "]\n";
}

void testNpy()
{
	getHeight();
	auto [west, south, east, north] = readExtent();

	String fileName1 = joinPath(PATH,"eastward_wind_00.npy");
	String fileName2 = joinPath(PATH,"northward_wind_00.npy");
	
	auto [word_size, dimZ, dimY, dimX] = readDim(fileName1);

	NpyArray dataArray1 = npy_load(fileName1.c_str());
	NpyArray dataArray2 = npy_load(fileName2.c_str());

	size_t size = dimZ * dimY * dimX;
	std::vector<float> data;
	data.resize(size * 2);

	float minValue = 1e+5;
	float maxValue = -minValue;
	size_t i = 0;
	for (auto z = 0; z < dimZ; z++)
	{
		for (auto y = 0; y < dimY; y++)
		{
			for (auto x = 0; x < dimX; x++, i++)
			{
				float val1 = getFloat(i, dataArray1);
				float val2 = getFloat(i, dataArray2);
				if (val1 > maxValue) maxValue = val1;
				if (val1 < minValue) minValue = val1;
				if (val2 > maxValue) maxValue = val2;
				if (val2 < minValue) minValue = val2;
				data[i * 2] = val1;
				data[i * 2 + 1] = val2;
			}
		}
	}

	String fileName = joinPath(PATH, "uv.raw");
	std::ofstream ofs(fileName, std::ios::binary);
	if (ofs)
	{
		ofs.write((char*)&data[0], data.size() * sizeof(float));
		ofs.close();
	}

	Json::Value json;
	json["dimZ"] = (Json::UInt64)dimZ;
	json["dimY"] = (Json::UInt64)dimY;
	json["dimX"] = (Json::UInt64)dimX;
	json["west"] = west;
	json["south"] = south;
	json["east"] = east;
	json["north"] = north;

	OCPP_LOG_INFO << json.toStyledString() << "\n";
	OCPP_LOG_INFO << "DataRange:[" << minValue << "," << maxValue << "]\n";
}